import { distributedSignalRService } from './DistributedSignalRService'
import { signalRService } from './SignalRService'
import { statisticsService } from './StatisticsService'

/**
 * 推送载荷数据接口
 */
interface PushPayload {
  data: any
  timestamp: string
  source: string
  updateType: 'full' | 'partial'
  operationType: string
  triggerUser: string
  pushId: string
}

/**
 * 推送来源类型
 */
type PushSource = 'system' | 'inventory_operation' | 'manual_refresh' | 'system_update'

/**
 * 操作类型
 */
type OperationType = 'inbound' | 'outbound'

/**
 * 全局统计数据推送服务
 * 负责在任何地方触发统计数据的全量推送，不依赖于特定页面或组件
 */
class GlobalStatisticsPushService {
  private isPushing = false
  private readonly useDistributedSignalR = true
  private readonly pushTimeout = 2000 // 推送锁定时间（毫秒）
  private readonly maxRetries = 2 // 最大重试次数

  /**
   * 触发全量统计数据推送给所有在线用户
   * @param triggerSource 触发来源 
   * @param triggerUser 触发用户
   * @param operationType 操作类型
   */
  async triggerGlobalStatisticsPush(
    triggerSource: PushSource = 'system',
    triggerUser: string = 'system',
    operationType: string = 'data_update'
  ): Promise<boolean> {
    if (this.isPushing) {
      console.log('⏳ 全量统计推送正在进行中，跳过重复请求')
      return false
    }

    try {
      return await this.executeWithLock(async () => {
        console.log(`🌍 开始全量统计数据推送 [${triggerSource}] [${operationType}]...`)

        // 获取最新的完整统计数据
        const fullData = await statisticsService.getDashboardData()

        if (fullData.code !== 200 || !fullData.data) {
          console.warn('⚠️ 获取统计数据失败，无法进行全量推送')
          return false
        }

        const pushPayload: PushPayload = {
          data: fullData.data,
          timestamp: new Date().toISOString(),
          source: triggerSource,
          updateType: 'full',
          operationType,
          triggerUser,
          pushId: this.generatePushId()
        }

        // 通过SignalR推送给所有在线用户
        const pushSuccess = await this.executePush(pushPayload)

        if (pushSuccess) {
          console.log(`✅ 全量统计推送完成 [${pushPayload.pushId}]`)
        }

        return pushSuccess
      })
    } catch (error) {
      console.error('❌ 全量统计推送失败:', error)
      return false
    }
  }

  /**
   * 使用锁定机制执行操作
   */
  private async executeWithLock<T>(operation: () => Promise<T>): Promise<T> {
    this.isPushing = true
    try {
      return await operation()
    } finally {
      setTimeout(() => {
        this.isPushing = false
      }, this.pushTimeout)
    }
  }

  /**
   * 执行推送操作，包含重试机制
   */
  private async executePush(pushPayload: PushPayload): Promise<boolean> {
    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        if (this.useDistributedSignalR && distributedSignalRService.isInventoryConnected) {
          return await this.pushViaDistributedSignalR(pushPayload)
        } else if (signalRService.isConnected && signalRService.connection) {
          return await this.pushViaSignalR(pushPayload)
        } else {
          console.warn('⚠️ SignalR未连接，无法进行全量推送')
          return false
        }
      } catch (error) {
        console.warn(`⚠️ 推送尝试 ${attempt}/${this.maxRetries} 失败:`, error)
        if (attempt === this.maxRetries) {
          throw error
        }
        // 等待一段时间后重试
        await new Promise(resolve => setTimeout(resolve, 1000))
      }
    }
    return false
  }

  /**
   * 生成唯一推送ID
   */
  private generatePushId(): string {
    return `statistics_push_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  /**
   * 通过分布式SignalR推送
   */
  private async pushViaDistributedSignalR(pushPayload: PushPayload): Promise<boolean> {
    try {
      const promises = [
        distributedSignalRService.sendToAllInventoryUsers('ReceiveGlobalStatisticsUpdate', pushPayload),
        distributedSignalRService.sendToAllInventoryUsers('ReceiveGlobalDataUpdate', pushPayload)
      ]
      
      await Promise.all(promises)
      console.log('✅ 分布式SignalR统计推送完成')
      return true
    } catch (error) {
      console.error('❌ 分布式SignalR统计推送失败:', error)
      return false
    }
  }

  /**
   * 通过原有SignalR推送
   */
  private async pushViaSignalR(pushPayload: PushPayload): Promise<boolean> {
    try {
      const connection = signalRService.connection!
      const promises = [
        connection.invoke('SendToAll', 'ReceiveGlobalStatisticsUpdate', pushPayload),
        connection.invoke('SendToAll', 'ReceiveGlobalDataUpdate', pushPayload)
      ]
      
      await Promise.all(promises)
      console.log('✅ 原有SignalR统计推送完成')
      return true
    } catch (error) {
      console.error('❌ 原有SignalR统计推送失败:', error)
      return false
    }
  }

  /**
   * 出入库操作后触发推送
   */
  async triggerInventoryOperationPush(
    operationType: OperationType,
    goodsName: string,
    quantity: number,
    operatorName: string
  ): Promise<boolean> {
    const operation = operationType === 'inbound' ? '入库' : '出库'
    console.log(`📦 触发${operation}操作推送:`, {
      goodsName,
      quantity,
      operatorName
    })

    return await this.triggerGlobalStatisticsPush(
      'inventory_operation',
      operatorName,
      `${operation}_${goodsName}_${quantity}件`
    )
  }

  /**
   * 数据手动刷新后触发推送
   */
  async triggerManualRefreshPush(userName: string): Promise<boolean> {
    return await this.triggerGlobalStatisticsPush(
      'manual_refresh',
      userName,
      '手动刷新统计数据'
    )
  }

  /**
   * 系统自动更新后触发推送
   */
  async triggerSystemUpdatePush(): Promise<boolean> {
    return await this.triggerGlobalStatisticsPush(
      'system_update',
      'system',
      '系统自动更新'
    )
  }

  /**
   * 检查当前推送状态
   */
  isPushingInProgress(): boolean {
    return this.isPushing
  }

  /**
   * 获取推送服务状态信息
   */
  getStatus(): {
    isPushing: boolean
    useDistributedSignalR: boolean
    distributedConnected: boolean
    signalRConnected: boolean
  } {
    return {
      isPushing: this.isPushing,
      useDistributedSignalR: this.useDistributedSignalR,
      distributedConnected: distributedSignalRService.isInventoryConnected,
      signalRConnected: signalRService.isConnected
    }
  }
}

// 导出单例实例
export const globalStatisticsPushService = new GlobalStatisticsPushService()
export default globalStatisticsPushService
